what’s this ?
最近稍稍有点空闲,复习一下基础知识。说起 JavaScript 这门语言让人头疼的地方, 就绕不开 this 关键字的指向问题。
经过孜孜不倦地翻阅各大 IT 牛人的博客和相关网站之后……
被虐的过程就不详细描述了!!
总之,学习完之后,我就 “人不住手” 地总结了一下学到的知识,分享给大家。
学习 this 的必要
众所周知,JavaScript 是一门基于原型的编程语言,我们可以通过使用关键词
new 和 this 来实现代码的复用。
通过学习 this 等相关知识,能帮助你更好了解这门语言的设计模式和特性,加深你对代码的理解与使用。
this 是什么?this 指向谁?
- this 是 JS 关键字,代表了一个空间地址。
- this 是一个指针,指向函数运行时所在的环境。
通俗讲,就是谁调用了函数,函数内的 this 就指向谁。因此,我们想知道 this 指向谁,就一定要清楚到底是谁调用了函数。(PS:哈哈哈,说了句废话。)
this 的四种调用
默认调用
独立函数调用时,this 指向 window 对象
1 | // 注意:这里不能使用let |
严格模式下,默认绑定的 this 指向 undefined 。
1 | ;(function() { |
对象调用
如果函数执行时有上下文对象,会把函数里的 this 默认绑定到这个上下文对象上。
1 | var a = 10 |
多层调用时,默认获取最后一层调用的上下文对象。
1 | var a = 10 |
call、apply、bind 强制绑定
通过 call、apply、bind 改变函数的 this 指向。
绑定后无论怎么调用,也不会改变其 this 指向。
1 | let obj = { |
new 绑定调用
老生常谈,先看看 JS 中 new 关键字做了什么:
- 在内存中创建一个新对象
- 将新对象的proto指向构造函数的原型 prototype 对象
- 将构造函数的作用域赋值给新对象,(this 指向新对象)
- 执行构造函数中的代码(给这个新对象加属性和方法)
- 返回新对象,如果这个函数没有返回其他对象。
得出结论:
使用 new 调用函数,返回的对象的 this 始终指向自身。
1 | function fn() { |
箭头函数的 this
箭头函数区别于以上介绍的运行规则,而是完全根据外部作用域来决定 this,但其父级是遵循 this 绑定规则的(即:如果箭头函数的父级的 this 指向 window,那么箭头函数的 this 也指向 window)
通过例子认识下:
1 | let obj={ |
上述例子,可以发现在 setTimeout 中传入函数时,函数中的 this 会指向 window 对象,那么怎样让 this 指向 obj 对象?
修改下代码:
1 | let obj={ |
发现在我们使用箭头函数之后,使其继承了父函数 obj.fn 的 this 指针,达到了如下相同效果:
1 | let obj = { |
看到这里,应该以及理解了箭头函数的 this 是继承来的意思。
让我们再通过几个例子方便去理解箭头函数中的 this。
例 1:
1 | let obj = { |
相信你一定很疑惑,为什么上述箭头函数里输出的是 window 对象,那么再看一段代码就清楚了。
例 2:
1 | let obj = { |
我们发现,obj 里的 this 指向的是全局的 window 对象,那么就很好理解了,箭头函数继承了 obj 中的 this,也指向了全局 window 对象。
最后,我们可以通过箭头函数实现强制绑定 this 的效果。
没修改前的代码:
1 | var a = 10 |
以上例子是我们讲解对象调用时的例子,我们不难发现,直接用 obj 对象去调用和独立调用时输出的结果不一致。如果你有仔细阅读文章的话,应该不难理解造成这种情形的原因。
接下来,我们通过箭头函数改造下代码,使我们复制的引用,独立调用时 this 也指向 obj。
修改后的代码:
1 | var a = 10 |
END
无论怎样,都别丢了快乐和努力。
转载分享,请标明出处。